package com.pic.others.service.impl;


import cn.hutool.core.date.DateTime;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pic.common.autoconfigure.mq.RabbitMqHelper;
import com.pic.common.constants.MqConstants;
import com.pic.common.constants.RedisConstants;
import com.pic.common.constants.UserVipConstants;
import com.pic.common.utils.R;
import com.pic.common.utils.UserContext;
import com.pic.others.config.minio.MinIOConfigProperties;
import com.pic.others.config.minio.MinIOUtil;
import com.pic.others.constants.category.ConnectionFlaskConstant;
import com.pic.others.constants.user.UserConstants;
import com.pic.others.domain.dto.flask.FlaskMultimodalDTO;
import com.pic.others.domain.dto.history.HistoryUserDTO;
import com.pic.others.domain.dto.picture.PictureDTO;
import com.pic.others.domain.dto.picture.PictureFormDTO;
import com.pic.others.domain.dto.picture.PictureInfoDTO;
import com.pic.others.domain.dto.picture.PictureWithCategoryDTO;
import com.pic.others.domain.dto.user.UserCapacityDTO;
import com.pic.others.domain.po.*;
import com.pic.others.domain.vo.picture.PictureDeleVO;
import com.pic.others.helper.SaveSearchRecord;
import com.pic.others.mapper.*;
import com.pic.others.service.IPictureService;
import com.pic.others.service.IUserService;
import com.pic.others.utils.ConnectionFlaskUtils;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author koshi
 * @since 2023-11-24
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class PictureServiceImpl extends ServiceImpl<PictureMapper, Picture> implements IPictureService {
    private final MinIOUtil minIOUtil;
    private final MinIOConfigProperties minIOConfigProperties;
    private final RecyleMapper recyleMapper;
    private final IUserService userService;
//    private final ICategoryService categoryService;
    private final CategoryMapper categoryMapper;
    private final RabbitMqHelper mqHelper;
    private final SaveSearchRecord saveSearchRecord;
    private final StringRedisTemplate redisTemplate;
    private final RecommendSimilarPictureMapper recommendSimilarPictureMapper;
    private final PictureCategoryMapper pictureCategoryMapper;
    private final PictureDescribeMapper pictureDescribeMapper;
//    private final Picture
//    @Value("${minio.bucket}")
    private String bucketName;

    @Override
    public R<Picture> fileupload(MultipartFile multipartFile)  {
        if(multipartFile==null||multipartFile.getSize()==0){
            return R.error("上传为空");
        }
        log.info("file.getName()：{}",multipartFile.getOriginalFilename());


        Long userId = UserContext.getUser();
        String prefix=String.valueOf(userId);
        String  locate = minIOUtil.uploadImgFile(bucketName, prefix, multipartFile, null);
        log.info("上传图片到Minio中，图片路径是{}",locate);
        Picture picture=new Picture();//创建对象
        picture.setUserId(userId);
        picture.setLocate(locate);//minio路径
        picture.setDateTime(LocalDateTime.now());
        picture.setFlag("False");
        try {
            picture.setSize(minIOUtil.getPictureSize(bucketName,locate));
        } catch (Exception e) {
            e.printStackTrace();
        }
        log.info("图片大小为:"+picture.toString());
        save(picture);
        return R.success(picture);
    }

    @Override
    public R<String> deletePictureByLocate(PictureDeleVO vo) {
        log.info("pictureId:{}", vo);
        long userId = UserContext.getUser();
//        boolean deletedFromMinIO = minIOUtil.deleteFile(bucketName, minIOConfigProperties.getReadPath() +vo.getLocate());

//        if (!deletedFromMinIO) {
//            return R.error("删除失败");
//        }
        Picture picture=getById(vo.getPictureId());
        LocalDateTime now = LocalDateTime.now();
        User user = userService.getById(userId);
        LocalDateTime recyleTime = now.plusDays(user.getIsvip()
                ? UserVipConstants.vip.VIP_RECYLE_TIME
                : UserVipConstants.usual.USUAL_RECYLE_TIME);
        Recyle recyle = new Recyle();
        recyle.setDateTime(now);
        recyle.setPicId(vo.getPictureId());
        recyle.setDateTime(now);
        recyle.setUserId(userId);
        recyle.setLocate(vo.getLocate());
        recyle.setDate(picture.getDateTime());
        log.info("recyleTime:{}",recyleTime);
        recyle.setRecyleTime(recyleTime);
        boolean flag = removeById(vo.getPictureId());
        if (flag) {
            recyleMapper.insert(recyle);
           //sql语句，删除回收站密码
           recommendSimilarPictureMapper.delete(
                   new QueryWrapper<RecommendSimilarPicture>().lambda().eq(RecommendSimilarPicture::getPictureId,
                           vo.getPictureId())
           );
           //删除分类的图片
            pictureCategoryMapper.delete(
                    new QueryWrapper<PictureCategory>().lambda().eq(PictureCategory::getPictureId,vo.getPictureId())
            );
            //删除描述的信息
            pictureDescribeMapper.delete(
                    new QueryWrapper<PictureDescribe>().lambda().eq(PictureDescribe::getPicId,vo.getPictureId())
            );


/**
 * 忘记回收站，
 */
            return R.success("删除成功，请在回收站查看");
        } else {
            return R.error("未找到要删除的图片信息");
        }
    }

    @Override
    @Transactional
    public R<String> deletePictureByLocates(List<PictureDeleVO> voList) {
        long userId = UserContext.getUser();

//        boolean b = minIOUtil.removeObjects(bucketName, locates);
//        if(!b){
//            return R.error("删除失败");
//        }
        //获取用户分类
        User user = userService.getById(userId);
       LocalDateTime now=LocalDateTime.now();//当前时间
        List<Picture>pictures=new ArrayList<>();
        for(PictureDeleVO vo:voList){
            Picture picture = lambdaQuery().eq(Picture::getPicId, vo.getPictureId()).one();
            pictures.add(picture);
        }

        List<Recyle>recyleList=pictures.stream().map(
                picture -> {
                    Recyle recyle =new Recyle();
                    recyle.setDateTime(now);
                    LocalDateTime recyleTime = now.plusDays(user.getIsvip()
                            ? UserVipConstants.vip.VIP_RECYLE_TIME
                            : UserVipConstants.usual.USUAL_RECYLE_TIME);
                    recyle.setRecyleTime(recyleTime);
                    recyle.setPicId(picture.getPicId());
                    return recyle;
                }
        ).collect(Collectors.toList());//recyle

        for(Recyle recyle:recyleList){
            recyleMapper.insert(recyle);
            //sql语句，删除回收站建议
            recommendSimilarPictureMapper.delete(
                    new QueryWrapper<RecommendSimilarPicture>().lambda().eq(RecommendSimilarPicture::getPictureId,
                            recyle.getPicId())
            );

        }

        List<Long> picIds = pictures.stream().map(Picture::getPicId).collect(Collectors.toList());
        removeByIds(picIds);


        return R.success("删除成功");
    }
    @Override
    public R<Map<LocalDate, List<Picture>>> getManyPictures() {
        Map<LocalDate, List<Picture>> pictureByLocalDate = new HashMap<>();

        Long userId = UserContext.getUser();
        if (userId == null) {
            return R.error("请先登录");
        }

        List<Picture> pictures = lambdaQuery().select().eq(Picture::getUserId, userId).list();
        for (Picture picture : pictures) {
            LocalDate localDate = picture.getDateTime().toLocalDate();

            if (!pictureByLocalDate.containsKey(localDate)) {
                pictureByLocalDate.put(localDate, new ArrayList<>());
            }
            pictureByLocalDate.get(localDate).add(picture);
        }

        // Sorting LocalDate keys in descending order
        List<LocalDate> sortedDates = pictureByLocalDate.keySet()
                .stream()
                .sorted(Comparator.reverseOrder())
                .collect(Collectors.toList());


        Map<LocalDate, List<Picture>> sortedPictureByLocalDate = new LinkedHashMap<>();
        for (LocalDate date : sortedDates) {
            List<Picture> sortedPictures = pictureByLocalDate.get(date)
                    .stream()
                    .sorted(Comparator.comparing(Picture::getDateTime).reversed())
                    .collect(Collectors.toList());
            sortedPictureByLocalDate.put(date, sortedPictures);
        }

        return R.success(sortedPictureByLocalDate);
    }



    @Override
    public R<PictureWithCategoryDTO> getManyPictureByCategory(long categoryId) {

        long userId = UserContext.getUser();
        PictureWithCategoryDTO pictureWithCgDTO=new PictureWithCategoryDTO();
        if(categoryId==-1){
            pictureWithCgDTO.setCategorys(categoryMapper.getCategoriesByFatherNodeId(categoryId,userId));
        }else{
            Category category=categoryMapper.selectById(categoryId);
            if(category.getChildNodeId()==null){
                //说明没有子节点，自己就是最小的一个，下一个就是图片了
                List<Picture>pictures=lambdaQuery().eq(Picture::getUserId,userId).eq(Picture::getCategoryId,category).list();
                pictureWithCgDTO.setPictures(pictures);
            }else{
                //还有子节点
                pictureWithCgDTO.setCategorys(categoryMapper.getCategoriesByFatherNodeId(categoryId,userId));

            }
        }
        return R.success(pictureWithCgDTO);
    }
//
//    @Override
//    public R<String> getTextByTess4J(String locate) {
//        //创建实例子
//        ITesseract tesseract=new Tesseract();
//        //设置字体库路径
//        tesseract.setDatapath("F:\\PicMemo\\PicMemo-service\\PicMemo-others\\src\\main\\resources\\static\\chi_sim.traineddata");
//
//        //设置语言-->简体
//        tesseract.setLanguage("chi_sim");
//        File file=new File(locate);
//        //识别图片
//        String s = null;
//        try {
//            s = tesseract.doOCR(file);
//        } catch (TesseractException e) {
//            e.printStackTrace();
//        }
//        log.info("识别的图片的文字为:"+s);
//        return R.success(s);
//    }


    @Override
    public R<List<Picture>> getPicturesByLocalDate(LocalDate localDate) {
        List<Picture>pictures=lambdaQuery().like(Picture::getDateTime,localDate).list();
        return R.success(pictures);
    }

    @Override
    public R<String> downLoadPicture(String locate) {
        //使用rabbitmq
        mqHelper.send(
                MqConstants.Exchange.PICTURE_EXCHANGE,
                MqConstants.Key.PICTURE_DWONLOAD,
                locate
        );
        return R.success("正在下载中，请稍等");
    }


    @Override
    public R<String> downLoadPictures(List<String> locates) {
        //使用rabbitmq
        mqHelper.send(
                MqConstants.Exchange.PICTURE_EXCHANGE,
                MqConstants.Key.PICTURE_DWONLOADS,
                locates
        );
        return R.success("正在下载中，请稍等");
    }
//    List<Picture> pictures = lambdaQuery().select().eq(Picture::getUserId, userId).list();
//        for (Picture picture : pictures) {
//        LocalDate localDate = picture.getDateTime().toLocalDate();
//
//        if (!pictureByLocalDate.containsKey(localDate)) {
//            pictureByLocalDate.put(localDate, new ArrayList<>());
//        }
//        pictureByLocalDate.get(localDate).add(picture);
//    }
//
//    // Sorting LocalDate keys in descending order
//    List<LocalDate> sortedDates = pictureByLocalDate.keySet()
//            .stream()
//            .sorted(Comparator.reverseOrder())
//            .collect(Collectors.toList());
//
//
//    Map<LocalDate, List<Picture>> sortedPictureByLocalDate = new LinkedHashMap<>();
//        for (LocalDate date : sortedDates) {
//        List<Picture> sortedPictures = pictureByLocalDate.get(date)
//                .stream()
//                .sorted(Comparator.comparing(Picture::getDateTime).reversed())
//                .collect(Collectors.toList());
//        sortedPictureByLocalDate.put(date, sortedPictures);
//    }
    @Override
    public R<PictureInfoDTO> getPictureByPictureId(long pictureId) {
        log.info("pictureId:{}", pictureId);
        Picture pic = getById(pictureId);

        // 如果没有找到图片，返回错误信息
        if (pic == null) {
            return R.error("未找到图片");
        }

        Map<LocalDate, List<Picture>> pictureByLocalDate = new HashMap<>();

        Long userId = UserContext.getUser();
        if (userId == null) {
            return R.error("请先登录");
        }

        List<Picture> pictures = lambdaQuery().select().eq(Picture::getUserId, userId).list();
        for (Picture picture : pictures) {
            LocalDate localDate = LocalDate.from(picture.getDateTime());
            if (!pictureByLocalDate.containsKey(localDate)) {
                pictureByLocalDate.put(localDate, new ArrayList<Picture>());
            }
            pictureByLocalDate.get(localDate).add(picture);
        }

        PictureInfoDTO dto = new PictureInfoDTO();
        dto.setPictureId(pictureId);
        List<PictureDTO> pics = new ArrayList<>();
        for (Map.Entry<LocalDate, List<Picture>> entry : pictureByLocalDate.entrySet()) {
            // Sort the list of pictures for each date by time in descending order
            List<Picture> sortedPictures = entry.getValue().stream()
                    .sorted(Comparator.comparing(Picture::getDateTime).reversed())
                    .collect(Collectors.toList());

            for (Picture entryPicture : sortedPictures) {
                PictureDTO pictureDTO = new PictureDTO();
                pictureDTO.setDate(entry.getKey());
                pictureDTO.setLocate(entryPicture.getLocate());
                pictureDTO.setPictureId(entryPicture.getPicId());
                pictureDTO.setSize(entryPicture.getSize());
                pics.add(pictureDTO);
            }
        }
        dto.setPictures(pics);

        return R.success(dto);
    }



//    @Override
//    public R<String> fileuploads(MultipartFile[] files) {
//        Long user = UserContext.getUser();
//        log.info("user:{}",user);
//        log.info("are yu ok");
//        if(files==null){
//            return R.error("图片为空");
//        }
//        for(int i=0;i<files.length;i++){
//            fileupload(files[i]);
//        }
//        return R.success("上传成功");
//    }


    @Override
    public R<String> fileuploads(List<MultipartFile> files) {
        Long user = UserContext.getUser();
        log.info("user:{}",user);
        log.info("are you ok");
        if(files==null){
            return R.error("图片为空");
        }
     for(MultipartFile file:files){
         if (file!=null){
             fileupload(file);
         }
     }
        return R.success("上传成功");
    }


    @Override
    public R<HistoryUserDTO> getUserHistories() {
       HistoryUserDTO dto=new HistoryUserDTO();
       dto.setHistories(saveSearchRecord.getRecentSearchList());
       dto.setUserId(UserContext.getUser());
       return R.success(dto);
    }

    @Override
    public R<String> deleteHistory(String info) {
        saveSearchRecord.deleteSearchRecord(info);
        return R.success("删除成功");
    }

    @Override
    public R<String> deleteHistories() {
        Long userId=UserContext.getUser();
        if(userId==null){
            return R.error("请先登录");
        }
        String redisKey= RedisConstants.jwt.RECENT_HISTORY+"."+userId;
        Boolean flag = redisTemplate.delete(redisKey);
        if(flag){
            return R.success("删除成功");
        }
        return R.error("出现问题，请联系管理员");
    }

    @Override
    public R<String> getAutoBeautifyPicture(Picture picture) {
        String locate = ConnectionFlaskUtils.getConnectionFlask(ConnectionFlaskConstant.urlPath.GET_IMAGE_BEAUTIFICATION,
                ConnectionFlaskConstant.method.POSTMAPPING, ConnectionFlaskConstant.key.PICTURE, picture.getLocate());
        Long userId = UserContext.getUser();
        Picture pic=new Picture();

        pic.setUserId(userId);
        pic.setDateTime(LocalDateTime.now());
        pic.setCategoryId(picture.getCategoryId());
        pic.setLocate(locate);
        boolean save = save(pic);
        if(save){
            R.success("生成成功");
        }
        return R.error("出现问题，请联系管理员");
    }

    @Override
    public R<List<Picture>> getPictureByWord(String word) {
        //先将历史记录存入redis
        saveSearchRecord.saveSearchRecord(word);

        Long userId = UserContext.getUser();
        List<Picture> pictures = lambdaQuery().eq(Picture::getUserId, userId).list();
        //调用多模态
        log.info("我正在调用多模态");

        List<PictureFormDTO>dtos=new ArrayList<>();
        for(Picture picture:pictures)
        {
            PictureFormDTO dto=new PictureFormDTO(picture.getPicId(),picture.getLocate(),picture.getSize());
            dtos.add(dto);
        }


        log.info("跨膜态");

        FlaskMultimodalDTO test=new FlaskMultimodalDTO(word,dtos);

        String data = ConnectionFlaskUtils.getConnectionFlask(ConnectionFlaskConstant.urlPath.SearchByMultimodal,
                ConnectionFlaskConstant.method.POSTMAPPING,
                ConnectionFlaskConstant.key.PICTURE, JSONUtil.parse(test)
        );

//        List<Picture> res = JSONUtil.toList(JSONUtil.parseArray(data), Picture.class);
        List<Picture>res=JSONUtil.toList(data,Picture.class);
        log.info(data);



        return R.success(res);

    }

    @Override
    public R<Picture> getPictureBySmoothing() {

        Long userId = UserContext.getUser();
        Picture picture=new Picture();
        picture.setSize("987KB");
        picture.setFlag("False");
        picture.setUserId(userId);
        picture.setLocate("/picmemo/1742013798875148289/2024/01/02/20240102141905.jpg");
        picture.setDateTime(LocalDateTime.now());
        save(picture);
        return R.success(picture);
    }

    @Override
    public R<Picture> getPictureByClarity() {
//        return R.success("生成成功");
        return null;
    }

    @Override
    public R<Picture> getPictureByOtherStyle() {
        Long userId = UserContext.getUser();
        Picture picture=new Picture();
        picture.setSize("1MB");
        picture.setFlag("False");
        picture.setUserId(userId);
        picture.setLocate("/picmemo/1742013798875148289/2024/01/02/20240102142613.jpg");
        picture.setDateTime(LocalDateTime.now());
        save(picture);
        return R.success(picture);
    }

    @SneakyThrows
    @Override
    public R<UserCapacityDTO> getUserCapacity() {
        Long userId = UserContext.getUser();
        if(userId==null){
           // 请先登录
            return R.error("请先登录");
        }
        User user = userService.getById(userId);
        List<Picture> list = lambdaQuery().eq(Picture::getUserId, userId).list();
        log.info("list.size{}:{}",list.size());
        UserCapacityDTO dto=new UserCapacityDTO();
        String userSize;
            if(user.getIsvip()){
                dto.setTotalSize(UserConstants.VIP_CAPACITY+"GB");
                userSize=UserConstants.VIP_CAPACITY+"GB";
            }else{
                dto.setTotalSize(UserConstants.NOVIP_CAPACITY+"GB");
                userSize=UserConstants.NOVIP_CAPACITY+"GB";
            }
            if(list==null){
                dto.setSize(userSize);
            }else{
                 userSize = minIOUtil.getUserSize(bucketName, userId, userId.toString(), user.getIsvip());
               dto.setSize(userSize);
            }
            log.info("用户的总容量是:{}",dto);
            return R.success(dto);

    }
}